import * as THREE from 'three';
// import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {FlyControls} from 'three/examples/jsm/controls/FlyControls.js';
import {TWEEN} from 'three/examples/jsm/libs/tween.module.min';
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader';
import {GLTFExporter} from 'three/examples/jsm/exporters/GLTFExporter';
import {DRACOLoader} from 'three/examples/jsm/loaders/DRACOLoader';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import {GUI} from 'three/examples/jsm/libs/dat.gui.module.js';
import {baseUrl} from '../../js/base.js';
import {OrbitControls} from './no_pack_js/OrbitControls';

import '../../css/base.css';
import {Face3, Geometry} from "three/examples/jsm/deprecated/Geometry";
import {ShapeGeometry} from "three";

let body = document.body,
    canvas = document.getElementById('canvas');
let renderer,
    scene,
    camera; // 场景、相机、渲染器

let stats, // 性能检测器
    orbitControls, // 控制器
    flyControls,
    clock = new THREE.Clock();

// 建筑物楼层每层数据
let buildingParams = window.buildingParams = {
    0: {
        floorNumber: 0,
        floorH: 6,
        position: new THREE.Vector3(),
        object: null,
        userData: null
    }
};

let buildingGroup = new THREE.Group();
let mouse = new THREE.Vector2(), // 指针位置
    point = null, // 指针点击位置
    mouseClick = new THREE.Vector2(); // 指针点击位置
let raycasterObject = []; // 选中的楼层对象
let raycaster = new THREE.Raycaster(); // 射线

let faceGroup = new THREE.Group(),  // 画面的组
    face,
    lineGroup = new THREE.Group(), // 画线的组
    line, // 画玩的线对象
    mousePoint; // 标点是跟随鼠标的点
let pointsList = []; // 画点、线、面临时存放的点数据

// gui 操作参数
const guiParams = window.guiParams = {
    open: true,
    drawPoint: false,
    drawLine: false,
    drawFace: false,
    setUpFloor: false,
    selectFloorActive: -1, // 选中的楼层
    selectFloor: [-1, 0, 1, 2, 3],
};

// 单层楼层点、线、面的数据
let floorParams = window.floorParams = {
    // 单层楼点数据
    points: [{
        'name': '0',
        'floorNumber': 0,
        'point': {
            'x': 59.81369177218892,
            'y': 1,
            'z': -1.9863392807017988
        }
    }, {
        'name': '0',
        'floorNumber': 0,
        'point': {
            'x': 30.442092286177164,
            'y': 1,
            'z': -5.988729826214325
        }
    }, {
        'name': '0',
        'floorNumber': 0,
        'point': {
            'x': 25.10135012701729,
            'y': 1,
            'z': 39.06534862281782
        }
    }, {
        'name': '0',
        'floorNumber': 0,
        'point': {
            'x': 33.568529867378516,
            'y': 1,
            'z': 30.646163890076195
        }
    }, {
        'name': '1',
        'floorNumber': 1,
        'point': {
            'x': 21.862205763706953,
            'y': 1,
            'z': 43.54129187011722
        }
    }, {
        'name': '1',
        'floorNumber': 1,
        'point': {
            'x': 0.9603323313979146,
            'y': 1,
            'z': 48.7016536008484
        }
    }, {
        'name': '1',
        'floorNumber': 1,
        'point': {
            'x': 0.5207947031863966,
            'y': 1,
            'z': 1.179041983822117
        }
    }, {
        'name': '2',
        'floorNumber': 2,
        'point': {
            'x': -19.24502268558758,
            'y': 1,
            'z': 35.21106715891918
        }
    }, {
        'name': '2',
        'floorNumber': 2,
        'point': {
            'x': 22.347041727669136,
            'y': 1,
            'z': 51.55862585449218
        }
    }, {
        'name': '2',
        'floorNumber': 2,
        'point': {
            'x': 45.83005636359384,
            'y': 1,
            'z': 30.507236583340955
        }
    }, {
        'name': '2',
        'floorNumber': 2,
        'point': {
            'x': 44.40977488890209,
            'y': 1,
            'z': 38.22366215052756
        }
    }, {
        'name': '2',
        'floorNumber': 2,
        'point': {
            'x': 34.343675210192245,
            'y': 1,
            'z': 39.143950237239096
        }
    }, {
        'name': '3',
        'floorNumber': 3,
        'point': {
            'x': -41.70370930828225,
            'y': 1,
            'z': 33.7295105287823
        }
    }, {
        'name': '3',
        'floorNumber': 3,
        'point': {
            'x': -48.50065297950898,
            'y': 1,
            'z': 31.520644731963785
        }
    }, {
        'name': '3',
        'floorNumber': 3,
        'point': {
            'x': -31.941464152505766,
            'y': 1,
            'z': 36.220968370407405
        }
    }],
    // 单层楼线数据
    lines: [{
        'name': '0',
        'floorNumber': 0,
        'points': [[56.38492850271006, 1, -47.89372069981417], [3.694515668706096, 1, 26.266998737642325], [-66.64355436603799, 1, -25.805319943338617]],
        'object': null
    }, {
        'name': '1',
        'floorNumber': 1,
        'points': [[62.764280804993376, 1, -28.682749590368502], [37.70442371001562, 1, 56.79135290527347], [13.725774627677907, 1, 24.091310180664067], [-14.879548649931657, 1, 17.609270368936876], [-14.060337530455378, 1, 34.79135290527347], [-13.963718696602633, 1, 34.79135290527344]],
        'object': null
    }, {
        'name': '2',
        'floorNumber': 2,
        'points': [[-9.073790201109041, 1, -8.14015671306501], [-27.770881177917524, 1, 17.367222779455517], [-4.881545814909103, 1, 39.15863195800782], [37.98604989903403, 1, 22.058625854492192], [38.00138653037596, 1, 22.05862585449222]],
        'object': null
    }],
    // 单层楼面数据
    faces: [{
        'name': '0',
        'floorNumber': 0,
        'points': [[48.19543693664178, 1, 25.524091072088993], [43.42621255948951, 1, 5.478211594660564], [9.343681417964895, 1, 29.52017499366795], [-14.563422550139215, 1, 40.6586441503631], [-14.563422550139215, 1, 40.6586441503631]],
        'object': null
    }, {
        'name': '1',
        'floorNumber': 1,
        'points': [[3.2562639370668762, 1, -31.755361027976875], [-45.79662199505052, 1, 43.54135290527344], [54.59824461562726, 1, 34.25374574936322], [54.59824461562726, 1, 34.25374574936322]],
        'object': null
    }, {
        'name': '2',
        'floorNumber': 2,
        'points': [[-63.14126860012775, 1, 3.847754136263376], [-40.379392635945614, 1, 31.096754418996113], [9.648094166180634, 1, 38.20272745012694], [54.41716611130166, 1, 30.037158720386657], [54.15405120269154, 1, 30.037154782530877]],
        'object': null
    }, {
        'name': '3',
        'floorNumber': 3,
        'points': [[-59.976867803047874, 1, 0.6244902557722014], [-50.840403093698406, 1, 22.758265451262986], [-30.50407068969907, 1, 44.417158903797244], [-19.9458444844556, 1, 33.366194964437724], [61.246426804556904, 1, 37.611604504348165], [61.24642680455203, 1, 37.611604504348165]],
        'object': null
    }]

};

// 跨层楼层点、线、面的数据
let floorsParams = window.floorsParams = {
    // 跨层楼点数据
    points: [{
        name: '',
        points: [{
            name: '',
            floorNumber: 0,
            point: new THREE.Vector3()
        }]
    }],
    // 跨层楼线数据
    lines: [{
        name: '',
        points: [{
            name: '',
            floorName: 0,
            point: new THREE.Vector3()
        }]
    }],
    // 跨层区域数据
    box: [{
        name: '',
        startFloorNumber: 0,
        endFloorNumber: 1,
        points: [new THREE.Vector3()]
    }]
};

// 初始化场景
function initCSR() {
    const w = canvas.offsetWidth;
    const h = canvas.offsetHeight;

    camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 10000);
    camera.position.set(0, 60, 100);

    window.scene = scene = new THREE.Scene();
    // scene.background = new THREE.Color(0xefefef);
    // scene.fog = new THREE.Fog( 0xefefef, 100, 500 );

    renderer = new THREE.WebGLRenderer({
        canvas,
        antialias: true,
        alpha: true,
        premultipliedAlpha: true
    });
    renderer.outputEncoding = THREE.sRGBEncoding;
    renderer.sortObjects = false;
    camera.updateProjectionMatrix();
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(w, h, false);
}

// 初始化灯光
function initLight() {
    const ambientLight = new THREE.AmbientLight(0xFFFFFF, .6);
    scene.add(ambientLight);

    const directionalLight = new THREE.DirectionalLight(0xFFFFFF, 1);
    directionalLight.position.set(-1000, 1000, -1000);
    scene.add(directionalLight);
}

// 初始化模型
function initModel() {
    const gltfLoader = new GLTFLoader();
    // Optional: Provide a DRACOLoader instance to decode compressed mesh data
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('/static/examples/js/libs/draco/');
    gltfLoader.setDRACOLoader(dracoLoader);
    let textureLoader = new THREE.TextureLoader();
    const texture = textureLoader.load(baseUrl + 'static/images/floor.jpeg');
    gltfLoader.load(baseUrl + 'static/models/666.glb', onLoad, onProgress, onError);


    function onLoad(gltf) {
        const gltfScene = gltf.scene;
        // gltfScene.traverse((object) => {
        //   if(object.isMesh) {
        //     // object.material.transparent = false;
        //     // object.material.opacity = 1;
        //     if(object.material.transparent) {
        //       object.material = new THREE.MeshBasicMaterial({
        //         color: object.material.color,
        //         map: texture,
        //         transparent: true,
        //         opacity: object.material.opacity
        //       });
        //     } else {
        //       const meshBasicMaterial = new THREE.MeshBasicMaterial();
        //       meshBasicMaterial.copy(object.material)
        //       object.material = new THREE.MeshBasicMaterial({ ...meshBasicMaterial });
        //     }
        //   }
        // });
        gltfScene.children.forEach(value => {

            buildingParams[value.name] = {
                floorNumber: 0,
                floorH: 6,
                position: new THREE.Vector3(),
                object: value.clone(),
                // object: mesh.clone(),
                userData: value.userData
            };
            buildingGroup.add(buildingParams[value.name].object);
            buildingGroup.name = 'buildingGroup';
        });

        // 名对象名字处理一下
        Object.values(buildingParams)
            .forEach(value => {
                value.object.traverse(object => {
                    if (object.type === 'Mesh') {
                        const {
                            map,
                            color,
                            transparent,
                            opacity,
                        } = object.material;
                        object.material = new THREE.MeshBasicMaterial({
                            color,
                            map,
                            transparent,
                            opacity,
                            side: THREE.DoubleSide
                        });
                        // 	object.material = new THREE.MeshPhongMaterial({color, map, transparent, opacity, side: THREE.DoubleSide})
                        // 	object.material = new THREE.MeshLambertMaterial({color, map, transparent, opacity, side: THREE.DoubleSide})
                    }
                    if (object.name !== 'lines' && object.name !== 'floorLineGroup' && object.name !== 'floorFaceGroup') {
                        object.name = value.object.name;
                    }
                });
            });

        // 添加到射线识别的组
        raycasterObject.push(...buildingGroup.children);
        scene.add(buildingGroup);

        if (guiParams.open) {
            setTimeout(() => openOrCloseFloor(true), 0);
        }
    }

    // scene.add(new THREE.AxesHelper(100))

    function onProgress(xhr) {
        // console.log(xhr)
    }

    function onError(err) {
        console.error(err);
    }
}

// 设置模型居中
function setModelCenter(model) {
    model.updateWorldMatrix();
    const box = new THREE.Box3().setFromObject(model);
    const boxSize = box.getSize();
    const center = box.getCenter(new THREE.Vector3());
    model.translateY(-center.y);
    model.translateX(-center.x);
    model.translateZ(-center.z);
    model.position.copy(center);
    if (boxSize.x > boxSize.y) {
        camera.position.z = boxSize.x * -1;
    } else {
        camera.position.z = boxSize.y * -1;
    }
    camera.lookAt(0, 0, 0);
}

// 初始化控制器
function initControls() {
    {
        orbitControls = new OrbitControls(camera, canvas);
        orbitControls.enableDamping = true;
        orbitControls.screenSpacePanning = true;
        orbitControls.enableKeys = false;
        orbitControls.mouseButtons = {
            LEFT: THREE.MOUSE.PAN,
            MIDDLE: THREE.MOUSE.DOLLY,
            RIGHT: THREE.MOUSE.ROTATE
        };
        window.orbitControls = orbitControls;
    }
    // orbitControls.enabled = false

    {
        // flyControls = new FlyControls(camera, canvas);
        // flyControls.movementSpeed = 100
        // flyControls.rollSpeed = 1
        // flyControls.dragToLook = true
    }

    // setTimeout(() => {
    // 	orbitControls.dispose()
    // 	orbitControls = new OrbitControls(camera, canvas);
    // }, 2000)
    // orbitControls.target.set(0, 0, 0)
}

// 初始化帮手
function initHelper() {
    stats = new Stats();
    body.appendChild(stats.domElement);

    const gui = new GUI();

    gui.add(guiParams, 'open')
        .onChange((boolean) => {
            openOrCloseFloor(boolean);
        })
        .listen();

    mousePoint = drawPoint(scene, new THREE.Vector3());

    gui.add(guiParams, 'drawPoint')
        .onChange((boolean) => {
            if (boolean) mousePoint.material.color = new THREE.Color(0xFF0000);
        })
        .listen();
    gui.add(guiParams, 'drawLine')
        .onChange((boolean) => {
            if (boolean) {
                pointsList = []; // 清空

                const objectByName = buildingGroup.getObjectByName(guiParams.selectFloorActive);
                // 线信息处理
                line = new THREE.Group();
                line.name = 'line';
                lineGroup = objectByName.getObjectByName('floorLineGroup');
                if (!lineGroup) { // 如果保存这些线的组不存在则创建
                    lineGroup = new THREE.Group();
                    lineGroup.name = 'floorLineGroup';
                    objectByName.add(lineGroup);
                }

                mousePoint.material.color = new THREE.Color(0xFFFF00);
            } else {
                lineGroup = null;
            }
        })
        .listen();
    gui.add(guiParams, 'drawFace')
        .onChange((boolean) => {
            if (boolean) {
                pointsList = [];

                const objectByName = buildingGroup.getObjectByName(guiParams.selectFloorActive);
                // 面信息处理
                face = new THREE.Group();
                face.name = 'face';
                faceGroup = objectByName.getObjectByName('floorFaceGroup');
                if (!faceGroup) { // 如果保存这些线的组不存在则创建
                    faceGroup = new THREE.Group();
                    faceGroup.name = 'floorLineGroup';
                    objectByName.add(faceGroup);
                }

                mousePoint.material.color = new THREE.Color(0x0000FF);
            } else {
                faceGroup = null;
            }
        })
        .listen();

    gui.add(guiParams, 'selectFloorActive')
        .options(guiParams.selectFloor)
        .onChange(number => {
            console.log(number);
            guiParams.selectFloorActive = number;

            if (+number !== -1) {
                focusFloor(number);
            } else {
                // buildingGroup.children.forEach(value => {
                // 	raycasterObject.push(value)
                // })
            }

            const objectByName = buildingGroup.getObjectByName(guiParams.selectFloorActive);
            pointsList = [];
            // 线信息处理
            line = new THREE.Group();
            line.name = 'line';
            lineGroup = objectByName.getObjectByName('floorLineGroup');
            if (!lineGroup) { // 如果保存这些线的组不存在则创建
                lineGroup = new THREE.Group();
                lineGroup.name = 'floorLineGroup';
                objectByName.add(lineGroup);
            }
            // 面信息处理
            face = new THREE.Group();
            face.name = 'face';
            faceGroup = objectByName.getObjectByName('floorFaceGroup');
            if (!faceGroup) { // 如果保存这些线的组不存在则创建
                faceGroup = new THREE.Group();
                faceGroup.name = 'floorLineGroup';
                objectByName.add(faceGroup);
            }
        })
        .listen();
}

// 展开合并楼层
function openOrCloseFloor(boolean) {
    buildingGroup.children.forEach((value, index) => {
        new TWEEN.Tween({position: value.position.y}).to({
            position: boolean ? value.position.y + value.name * 30 :
                value.position.y - value.name * 30
        }, 500)
            .onUpdate(val => {
                value.position.setY(val.position);
            })
            .onComplete(value => {
                console.log(buildingGroup.children[index].name);
                console.log(buildingGroup.children[index].name * 12);
            })
            .start();
    });
}

// 响应式控制窗口大小
function onWindowResize() {
    renderer.setPixelRatio(window.devicePixelRatio);
    const width = canvas.offsetWidth;
    const height = canvas.offsetHeight;
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
    renderer.setSize(width, height, false);
}

// 渲染
function render() {
    if (orbitControls) orbitControls.update();
    if (flyControls) flyControls.update(clock.getDelta());
    if (TWEEN) TWEEN.update();
    renderer.render(scene, camera);
    if (stats) stats.update();
}

// 循环渲染
function animation() {
    requestAnimationFrame(animation);
    render();
}

// 添加监听器
function addEL() {
    window.addEventListener('resize', onWindowResize);
    canvas.addEventListener('pointerdown', mouseDown, false);
    canvas.addEventListener('pointermove', mouseMove, false);
    canvas.addEventListener('pointerup', mouseUp, false);
    canvas.addEventListener('dblclick', ev => {
        console.log(ev);
    }, false);
    canvas.onmouseup = function (ev) {
        console.log(JSON.stringify(pointsList));
        if (ev.button === 2) {
            if (guiParams.drawLine) {
                floorParams.lines.push({
                    name: guiParams.selectFloorActive,
                    floorNumber: +guiParams.selectFloorActive,
                    points: pointsList,
                    object: null
                });
            }
            if (guiParams.drawFace) {
                floorParams.faces.push({
                    name: guiParams.selectFloorActive,
                    floorNumber: +guiParams.selectFloorActive,
                    points: pointsList,
                    object: null
                });
            }

            // guiParams.selectFloorActive = -1
            guiParams.drawPoint = false;
            guiParams.drawLine = false;
            guiParams.drawFace = false;
        }
    };
}

// 按下
function mouseDown(e) {
    //
    mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
    mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;
    //
    raycaster.setFromCamera(mouse, camera);
    let intersectObjects = raycaster.intersectObjects(raycasterObject, true);
    console.log(intersectObjects);
    // 有拾取到东西
    if (intersectObjects.length) {
        const object = intersectObjects[0];
        // 保存鼠标按下的点位置-----为单击操作使用
        mouseClick.copy(mouse);

        // 画线的第一个点
        if (guiParams.drawLine || guiParams.drawFace) {
            console.log(pointsList);
            if (guiParams.selectFloorActive === object.object.name) {
                if (pointsList.length < 1) {
                    pointsList = [];
                    pointsList.push([object.point.x, 1, object.point.z]);
                    pointsList.push([object.point.x, 1, object.point.z]);
                } else {
                    pointsList.push([object.point.x, 1, object.point.z]);
                }
            }
        }
    }
}

// 移动
function mouseMove(e) {
    //
    mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
    mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;
    //
    raycaster.setFromCamera(mouse, camera);
    let intersectObjects = raycaster.intersectObjects(raycasterObject, true);

    // 有拾取到东西
    if (intersectObjects.length) {
        const object = intersectObjects[0];
        // 鼠标移动高亮
        hoverFloor(object.object.name);

        // 需要 让点 跟随鼠标
        if (guiParams.drawPoint || guiParams.drawLine || guiParams.drawFace) {
            if (mousePoint) {
                mousePoint.visible = true;
                mousePoint.position.copy(object.point);
            } else {
                mousePoint = drawPoint(scene, new THREE.Vector3());
            }
        }

        // 画线
        if (guiParams.drawLine) {
            pointsList.pop();
            pointsList.push([object.point.x, 1, object.point.z]);
            lineGroup.remove(line);
            line = drawLine(lineGroup, pointsList);
        }

        // 画面
        if (guiParams.drawFace) {
            pointsList.pop();
            pointsList.push([object.point.x, 1, object.point.z]);
            faceGroup.remove(face);
            // face = drawFace(faceGroup, pointsList);
            face = drawConcaveFace(faceGroup, pointsList);
        }

    } else {
        // 鼠标移动高亮
        hoverFloor(-1);

        // 隐藏跟随鼠标的点
        if (mousePoint) mousePoint.visible = false;
    }
}

// 弹起
function mouseUp(e) {
    //
    mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
    mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;
    //
    raycaster.setFromCamera(mouse, camera);
    let intersectObjects = raycaster.intersectObjects(raycasterObject, true);

    // 有拾取到东西
    if (intersectObjects.length) {
        const object = intersectObjects[0];
        // 单击了同一个位置
        if (mouseClick.equals(mouse)) {
            // 设置焦点
            guiParams.selectFloorActive = object.object.name; // active状态的楼层
            focusFloor(object.object.name);

            // 标点 guiParams.drawPoint 是否开启标点
            if (guiParams.drawPoint) {
                const currentlyClickedFloor = buildingGroup.getObjectByName(guiParams.selectFloorActive);
                let points = currentlyClickedFloor.getObjectByName('points');
                if (!points) {
                    points = new THREE.Group();
                    points.name = 'points';
                    currentlyClickedFloor.add(points);
                }
                drawPoint(points, new THREE.Vector3().copy(object.point.setY(0)));

                floorParams.points.push({
                    name: guiParams.selectFloorActive,
                    floorNumber: +guiParams.selectFloorActive,
                    point: new THREE.Vector3().copy(object.point.setY(1)),
                    // object: Object.values(buildingParams).filter(value => +value.object.name === +guiParams.selectFloorActive)[0] || null
                });
            }
        }
    }
}

// 启动
(function () {
    initCSR();
    initLight();
    initHelper();
    initModel();
    initControls();
    addEL();
    // setTimeout(() => render(), 100)
    animation();
})();

/**
 * 画点
 * @param pointGroup
 * @param point
 * @param options
 * @returns {Points}
 */
function drawPoint(pointGroup, point, options) {
    const {
        color,
        transparent,
        opacity,
        side,
        depthTest,
        isLine
    } = options || {};
    const material = new THREE.PointsMaterial({
        color: color || 0xFF0000,
        transparent: transparent || true,
        opacity: opacity || 1,
        side: side || THREE.FrontSide,
        depthTest: depthTest || true
    });
    //设置具有几何顶点的几何（Geometry）或缓冲区几何（BufferGeometry）设置顶点位置，看名字就知道了，一个是直接将数据保存在js里面的，另一个是保存在WebGL缓冲区内的，而且肯定保存到WebGL缓冲区内的效率更高
    const geometry = new Geometry();
    geometry.vertices.push(point);
    //使用Line方法将线初始化
    const p = new THREE.Points(geometry, material);
    p.name = 'point';
    pointGroup.add(p);
    return p;
}

/**
 * 画线
 * @param lineGroup 线添加到指定的组或者Object3D
 * @param pointList 线的点
 * @param options {color, transparent, opacity, side, depthTest, isLine}
 * @returns {Mesh} 线
 */
function drawLine(lineGroup, pointList, options) {
    const {
        color,
        transparent,
        opacity,
        side,
        depthTest,
        isLine
    } = options || {};
    const material = new THREE.LineBasicMaterial({
        color: color || 0xffFF00,
        transparent: transparent || true,
        opacity: opacity || 1,
        side: side || THREE.FrontSide,
        depthTest: depthTest || true
    });
    //设置具有几何顶点的几何（Geometry）或缓冲区几何（BufferGeometry）设置顶点位置，看名字就知道了，一个是直接将数据保存在js里面的，另一个是保存在WebGL缓冲区内的，而且肯定保存到WebGL缓冲区内的效率更高
    const geometry = new Geometry();
    pointList.forEach(value => {
        geometry.vertices.push(new THREE.Vector3(...value));
    });
    //使用Line方法将线初始化
    const line = new THREE[!isLine ? 'LineLoop' : 'Line'](geometry, material);
    line.name = 'line';
    lineGroup.add(line);
    return line;
}

/**
 * 画面
 * @param faceGroup 面添加到指定的组或者Object3D
 * @param pointList 面的点
 * @param options {color, transparent, opacity, side, depthTest}
 * @returns {Mesh} 面
 */
function drawFace(faceGroup, pointList, options) {
    const {
        color,
        transparent,
        opacity,
        side,
        depthTest
    } = options || {};
    const geometry = new Geometry();

    pointList.forEach(points => {
        geometry.vertices.push(new THREE.Vector3(...points));
    });
    const vector3 = new THREE.Vector3();
    const c = new THREE.Color(0xffffff);
    for (let i = 2; i < pointList.length; i++) geometry.faces.push(new Face3(0, i - 1, i, vector3, c, i));

    const material = new THREE.MeshBasicMaterial({
        color: color || 0xff0000,
        transparent: transparent || true,
        opacity: opacity || 1,
        side: side || THREE.FrontSide,
        depthTest: depthTest || true
    });
    face = new THREE.Mesh(geometry, material);
    face.name = 'face';
    faceGroup.add(face);
    return face;
}

function drawConcaveFace(faceGroup, pointList, options) {
    const {
        color,
        transparent,
        opacity,
        side,
        depthTest
    } = options || {};
    // 用来创建凹包多边形的点,一定要按顺序哦
    let points = pointList || [[-54.51656453437723, 1, 1.2589797085067005], [77.55965243483786, 1, -2.7014522917014316], [50.4712618179327, 1, 39.831863993281885], [61.294966872171635, 1, 17.906923970755788], [41.42827914953114, 1, 40.43287140358973], [52.46129981923488, 1, 25.300708035104805], [35.480088997645694, 1, 41.21410334221805], [45.91584726363737, 1, 3.147038614363776], [23.1326431353664, 1, 44.14930098879374], [14.715727847219249, 1, 4.227067838395428], [4.139243097593116, 1, 42.74382135933986], [-11.22812356725084, 1, 4.42859759204563], [-13.299133799029057, 1, 44.40443733941794], [-29.746566875327552, 1, 6.471678581871359], [-37.38846104792808, 1, 40.186931347900696], [-54.31886840085025, 1, 7.701349574558144], [-54.31886840085025, 1, 7.701349574558144]];
    let list = [];// 用来装点位的数组

    // 将目标数组改成Vector2 这里默认去掉高度y,当然如果你喜欢可以用其他轴的
    for (let i = 0; i < points.length; i++) list.push(new THREE.Vector2(points[i][0], points[i][2]));

    // 用这些点位生成一个 Geometry
    let geometry = new ShapeGeometry(new THREE.Shape(list));

    const material = new THREE.MeshBasicMaterial({
        color: color || 0xff0000,
        transparent: transparent || true,
        opacity: opacity || .5,
        side: side || THREE.BackSide,
        depthTest: depthTest || false
    });

    // 这就是你要的多边形啦
    let face = new THREE.Mesh(geometry, material);
    face.name = 'face';
    face.add(new THREE.AxesHelper());
    face.rotateX(Math.PI / 2);
    faceGroup.add(face);
    face.position.setY(1);
    return face;
}

drawConcaveFace(faceGroup);

// 聚焦 楼层
function focusFloor(number) {
    hoverFloor(number);
}

// hover 楼层
function hoverFloor(number) {
    // Object.values(buildingParams).forEach((value, index) => {
    // 	if (number === value.object.name || guiParams.selectFloorActive === value.object.name) {
    // 		value.object.traverse(object => {
    // 			if (object.type === 'Mesh') {
    // 				if (object.name !== 'point' && object.name !== 'line' && object.name !== 'face') {
    // 					object.material.transparent = true
    // 					object.material.opacity = 1
    // 				}
    // 			}
    // 		})
    // 	} else {
    // 		value.object.traverse(object => {
    // 			if (object.type === 'Mesh') {
    // 				if (object.name !== 'point' && object.name !== 'line' && object.name !== 'face') {
    // 					object.material.transparent = true
    // 					object.material.opacity = .8
    // 				}
    // 			}
    // 		})
    // 	}
    // })
}

// 获取并设置点
function getAndSetPoints() {
    floorParams.points.forEach(value => {
        const buildingParam = buildingParams[value.name];
        if (buildingParam.object.getObjectByName('points')) {
            const points = new THREE.Group();
            points.name = 'points';
        }
        drawPoint(buildingParam.object, new THREE.Vector3(...Object.values(value.point)));
    });
}

// 获取并设置线
function getAndSetLine() {
    floorParams.lines.forEach(value => {
        const buildingParam = buildingParams[value.name];
        if (buildingParam.object.getObjectByName('floorLineGroup')) {
            const floorLineGroup = new THREE.Group();
            floorLineGroup.name = 'floorLineGroup';
        }
        drawLine(buildingParam.object, value.points);
    });
}

// 获取并设置面
function getAndSetFace() {
    floorParams.faces.forEach(value => {
        const buildingParam = buildingParams[value.name];
        if (buildingParam.object.getObjectByName('floorFaceGroup')) {
            const floorLineGroup = new THREE.Group();
            floorLineGroup.name = 'floorFaceGroup';
        }
        drawLine(buildingParam.object, value.points, {isLine: true});
        drawConcaveFace(buildingParam.object, value.points);
    });
}

const interval = setInterval(() => {
    if (buildingGroup.getObjectByName('2')) {
        getAndSetPoints();
        getAndSetLine();
        getAndSetFace();
        clearInterval(interval);
    }
}, 800);

// setTimeout(() => {
//
// 	// Instantiate a exporter
// 	const gltfExporter = new GLTFExporter();
//
// 	function exportGLTF(input) {
//
// 		gltfExporter.parse(input, function (result) {
//
// 			if (result instanceof ArrayBuffer) {
// 				saveArrayBuffer(result, 'scene.glb');
// 			} else {
// 				const output = JSON.stringify(result, null, 2);
// 				console.log(output);
// 				saveString(output, 'scene.gltf');
// 			}
// 		}, {binary: true});
// 	}
//
// 	function saveString(text, filename) {
// 		save(new Blob([text], {type: 'text/plain'}), filename);
// 	}
//
// 	function saveArrayBuffer(buffer, filename) {
// 		save(new Blob([buffer], {type: 'application/octet-stream'}), filename);
// 	}
//
// 	function save(blob, filename) {
// 		link.href = URL.createObjectURL(blob);
// 		link.download = filename;
// 		link.click();
// 		// URL.revokeObjectURL( url ); breaks Firefox...
// 	}
//
// 	const link = document.createElement('a');
// 	link.style.display = 'none';
// 	document.body.appendChild(link); // Firefox workaround, see #6594
//
// 	for (let key in buildingParams) {
// 		let meshArr = [];
// 		let materialArr = [];
// 		buildingParams[key].object.rotateX(-90)
// 		console.log(buildingParams[key].object)
// 		buildingParams[key].object.traverse(function (child) {
// 			if (child.isMesh) {
// 				meshArr.push(child);
// 				materialArr.push(child.material);
// 			}
// 		});
//
// 		let geometry = new THREE.Geometry();
// 		for (let i = 0; i < meshArr.length; i++) {
// 			meshArr[i].updateMatrix();
// 			let geo = new THREE.Geometry();
// 			if (meshArr[i].geometry.type === "Geometry"){
// 				geo = meshArr[i].geometry
// 			} else {
// 				geo.fromBufferGeometry(meshArr[i].geometry)
// 			}
// 			geometry.merge(geo, meshArr[i].matrix, i)
// 			// geometry.merge(new THREE.Geometry().fromBufferGeometry(meshArr[i].geometry), meshArr[i].matrix, i);
// 		}
//
// 		let mesh = new THREE.Mesh(geometry, materialArr);
// 		mesh.scale.set(0.001, 0.001, 0.001)
//
// 		// mesh.rotateX(60)
// 		console.log(mesh)
// 		scene.add(mesh)
// 		// exportGLTF(mesh)
// 	}
//
//
// }, 800)
